
#ifndef INCLUDE_BUFFER
#define INCLUDE_BUFFER

#include <cstdint>
#include <string>
#include <vector>

class WriteReadBuffer
{
private:
    static constexpr int s_buffer_size = 1500;

public:
    explicit WriteReadBuffer(int buffer_size = s_buffer_size);
    int       ExpendBuffer(int expend_size = s_buffer_size);
    uint8_t * BufferData();
    uint8_t * BufferEnd();
    int       BufferFreeSize() const;
    int       BufferDataSize() const;
    void      MovePosition(int size);
    void      RemoveSize(int size);
    void      PushDataToBuffer(const uint8_t * data, int length);

private:
    std::vector<uint8_t> m_buffer_vec;
    int                  m_data_start_index;
    int                  m_data_end_index;
};

class WriteBuffer : public WriteReadBuffer
{
public:
    WriteBuffer();
    explicit WriteBuffer(int size);
    void WriteUint8(uint8_t data);
    void WriteUint16(uint16_t data);
    void WriteUint32(uint32_t data);
    void WriteUint64(uint64_t data);
    void WriteN(const uint8_t * data, int size);
    void WriteString(const std::string & content);
    void WriteString(const char * content, int length);
    void PrintFmt(const char * fmt, ...);
    void ReadUint8(uint8_t & data);
    void ReadUint16(uint16_t & data);
    void ReadUint32(uint32_t & data);
    void ReadUint64(uint64_t & data);
};

using Buffer=WriteBuffer;

class ReferenceBuffer
{
public:
    ReferenceBuffer(const uint8_t * data, int data_size);
    ~ReferenceBuffer();
    const uint8_t * Buffer() const;
    int             BufferSize() const;

private:
    const uint8_t * m_data_ptr;
    const int       m_data_length;
};

#endif
